﻿
Imports System.Threading

'another implementation of circle
Namespace std
    Public Class cycle(Of T As Class)
        Private Const defaultSize As Int64 = 128 * 1024
        'it will only failed when thread count is over this limitation
        Private Const reservedSize As Int64 = 1024
        Private Const minSize As Int64 = (reservedSize << 1)
        Private _last As Int32
        Private _first As Int32
        Private _buff() As T

        Public Sub clear()
            _last = 0
            _first = 0
        End Sub

        Public Sub New(ByVal size As Int64)
            If size < minSize Then
                size = minSize
            End If
            ReDim _buff(minSize - 1)
            clear()
        End Sub

        Public Sub New()
            Me.New(defaultSize)
        End Sub

        Public Function buff() As T()
            Return _buff
        End Function

        Private Function index(ByVal i As Int32) As Int32
            Return i Mod _buff.Length()
        End Function

        Public Function first() As Int32
            Return index(_first)
        End Function

        Public Function last() As Int32
            Return index(_last)
        End Function

        Public Function front() As T
            Return at(first())
        End Function

        Public Function back() As T
            Return at(last())
        End Function

        Public Function push_back(ByVal i As T) As Boolean
            If full() Then
                Return False
            Else
                Dim j As Int32 = 0
                j = index(Interlocked.Increment(_last) - 1)
                assert(_buff(j) Is Nothing)
                copy(_buff(j), i)
                Return True
            End If
        End Function

        Public Function pop_front(ByRef i As T) As Boolean
            If empty() Then
                Return False
            Else
                Dim j As Int32 = 0
                j = index(Interlocked.Increment(_first) - 1)
                While _buff(j) Is Nothing
                End While
                copy(i, _buff(j))
                _buff(j) = Nothing
                Return True
            End If
        End Function

        Public Function availableIndex(ByVal i As Int32) As Boolean
            Return i < _buff.Length() AndAlso i >= 0
        End Function

        Default Public Property at(ByVal i As Int32) As T
            Get
                If availableIndex(i) Then
                    Return _buff(i)
                Else
                    Return Nothing
                End If
            End Get
            Set(ByVal value As T)
                If availableIndex(i) Then
                    _buff(i) = value
                End If
            End Set
        End Property

        Public Function empty() As Boolean
            Return _last = _first
        End Function

        Public Function full() As Boolean
            Return _last = _first - reservedSize
        End Function
    End Class
End Namespace
